{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyM7vOFz/ctj6hEBoPcJqCn6",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/sugarforever/wtf-langchain/blob/main/04_Prompts/04_Prompts.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 04 提示词\n",
        "\n",
        "## 什么是提示词？\n",
        "\n",
        "提示词（`Prompt`）是指向模型提供的输入。这个输入通常由多个元素构成。`LangChain` 提供了一系列的类和函数，简化构建和处理提示词的过程。\n",
        "- 提示词模板（Prompt Template）：对提示词参数化，提高代码的重用性。\n",
        "- 示例选择器（Example Selector）：动态选择要包含在提示词中的示例\n",
        "\n",
        "## 提示词模板\n",
        "\n",
        "提示词模板提供了可重用提示词的机制。用户通过传递一组参数给模板，实例化图一个提示词。一个提示模板可以包含：\n",
        "1. 对语言模型的指令\n",
        "2. 一组少样本示例，以帮助语言模型生成更好的回复\n",
        "3. 向语言模型提出的问题"
      ],
      "metadata": {
        "id": "IkIusM-GD9MR"
      }
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Ceq3MMqkDutF",
        "outputId": "b71546ca-c764-40db-b8e9-c75da5aa357f"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.3/1.3 MB\u001b[0m \u001b[31m7.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m90.0/90.0 kB\u001b[0m \u001b[31m9.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.1/3.1 MB\u001b[0m \u001b[31m18.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.4/49.4 kB\u001b[0m \u001b[31m4.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "!pip install -q langchain==0.0.235"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain import PromptTemplate\n",
        "template = \"\"\"\n",
        "你精通多种语言，是专业的翻译官。你负责{src_lang}到{dst_lang}的翻译工作。\n",
        "\"\"\"\n",
        "\n",
        "prompt = PromptTemplate.from_template(template)\n",
        "prompt.format(src_lang=\"英文\", dst_lang=\"中文\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 36
        },
        "id": "JLEcB491EGTI",
        "outputId": "e01c7610-0776-4801-be39-b8d6816ee207"
      },
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'\\n你精通多种语言，是专业的翻译官。你负责英文到中文的翻译工作。\\n'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 2
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 创建模板\n",
        "\n",
        "`PromptTemplate` 类是 `LangChain` 提供的模版基础类，它接收两个参数：\n",
        "1. `input_variables` - 输入变量\n",
        "2. `template` - 模版"
      ],
      "metadata": {
        "id": "_DRl_mS9EUl8"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "multiple_input_prompt = PromptTemplate(\n",
        "    input_variables=[\"color\", \"animal\"],\n",
        "    template=\"A {color} {animal} .\"\n",
        ")\n",
        "multiple_input_prompt.format(color=\"black\", animal=\"bear\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 36
        },
        "id": "T349YtlREVlc",
        "outputId": "682a2e75-18f9-4aba-b2d6-18e2e5d7b07a"
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'A black bear .'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "#### 聊天提示词模板\n",
        "\n",
        "聊天模型，比如 `OpenAI` 的GPT模型，接受一系列聊天消息作为输入，每条消息都与一个角色相关联。这个消息列表通常以一定格式串联，构成模型的输入，也就是提示词。"
      ],
      "metadata": {
        "id": "SLaylT92Eeu_"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.prompts import (\n",
        "    ChatPromptTemplate,\n",
        "    PromptTemplate,\n",
        "    SystemMessagePromptTemplate,\n",
        "    AIMessagePromptTemplate,\n",
        "    HumanMessagePromptTemplate,\n",
        ")\n",
        "from langchain.schema import (\n",
        "    AIMessage,\n",
        "    HumanMessage,\n",
        "    SystemMessage\n",
        ")\n",
        "\n",
        "system_template=\"You are a professional translator that translates {src_lang} to {dst_lang}.\"\n",
        "system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)\n",
        "\n",
        "human_template=\"{user_input}\"\n",
        "human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)\n",
        "\n",
        "chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])\n",
        "chat_prompt.format_prompt(\n",
        "    src_lang=\"English\",\n",
        "    dst_lang=\"Chinese\",\n",
        "    user_input=\"Did you eat in this morning?\"\n",
        ").to_messages()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LH_VDH6iEjY8",
        "outputId": "3b1cad37-3375-4b50-9ebe-505b7085d471"
      },
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[SystemMessage(content='You are a professional translator that translates English to Chinese.', additional_kwargs={}),\n",
              " HumanMessage(content='Did you eat in this morning?', additional_kwargs={}, example=False)]"
            ]
          },
          "metadata": {},
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "#### 样本选择器"
      ],
      "metadata": {
        "id": "YL1RwGrXEyKg"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.prompts import PromptTemplate\n",
        "from langchain.prompts import FewShotPromptTemplate\n",
        "from langchain.prompts.example_selector import LengthBasedExampleSelector\n",
        "\n",
        "examples = [\n",
        "    {\"input\": \"happy\", \"output\": \"sad\"},\n",
        "    {\"input\": \"tall\", \"output\": \"short\"},\n",
        "    {\"input\": \"energetic\", \"output\": \"lethargic\"},\n",
        "    {\"input\": \"sunny\", \"output\": \"gloomy\"},\n",
        "    {\"input\": \"windy\", \"output\": \"calm\"},\n",
        "]\n",
        "example_prompt = PromptTemplate(\n",
        "    input_variables=[\"input\", \"output\"],\n",
        "    template=\"Input: {input}\\nOutput: {output}\",\n",
        ")\n",
        "example_selector = LengthBasedExampleSelector(\n",
        "    # 可选的样本数据\n",
        "    examples=examples,\n",
        "    # 提示词模版\n",
        "    example_prompt=example_prompt,\n",
        "    # 格式化的样本数据的最大长度，通过get_text_length函数来衡量\n",
        "    max_length=4,\n",
        "    # get_text_length: ...\n",
        ")\n",
        "dynamic_prompt = FewShotPromptTemplate(\n",
        "    example_selector=example_selector,\n",
        "    example_prompt=example_prompt,\n",
        "    prefix=\"Give the antonym of every input\",\n",
        "    suffix=\"Input: {adjective}\\nOutput:\",\n",
        "    input_variables=[\"adjective\"],\n",
        ")\n",
        "\n",
        "# 输入量极小，因此所有样本数据都会被选中\n",
        "print(dynamic_prompt.format(adjective=\"big\"))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Aei66914EywY",
        "outputId": "51606e73-35a0-4d95-9714-31cba534862a"
      },
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Give the antonym of every input\n",
            "\n",
            "Input: big\n",
            "Output:\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "example_selector.get_text_length(\"\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vehXwrdxG08-",
        "outputId": "b8665780-fbf7-4329-dd3d-5e0602837bf0"
      },
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1"
            ]
          },
          "metadata": {},
          "execution_count": 12
        }
      ]
    }
  ]
}